<?php

namespace wangk\openapi\openapi\oAuth;

use wangk\openapi\openapi\exception\AuthException;
use wangk\openapi\openapi\exception\BusinessException;
use wangk\openapi\openapi\exception\ExceptionHandler;
use wangk\openapi\openapi\exception\ExceptionType;
use wangk\openapi\openapi\exception\SystemException;
use wangk\openapi\openapi\exception\UnknownException;

class RequestClient
{

    /**生成sign*/
    public static function signature($param)
    {
        try{
            ksort($param);
            $string = '';
            foreach ($param as $key=>$value){
                $value = is_int($value)?(string)$value:$value;
                $string.= $key.'='.json_encode($value,JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
            }
            $encode = mb_detect_encoding($string, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
            if ($encode != null) {
                $string = mb_convert_encoding($string, 'UTF-8', $encode);
            }
        }catch (\Throwable $e){
            throw new BusinessException('签名失败',ExceptionType::SIGN_ERROR);
        }
        return strtoupper(md5($string));
    }


    /**
     * 发起请求
     * @throws ExceptionHandler
     * @throws BusinessException
     * @throws SystemException
     * @throws AuthException
     * @throws UnknownException
     */
    public static function request($url, $body, $header = [], $type='POST')
    {
        try{
            $type = strtoupper($type);
            switch ($type) {
                case 'POST':
                    $requestResponse = self::curlPost($url, $body, $header);
                    break;
                case 'GET':
                    $requestResponse = self::curlGet($url, $body,$header);
                    break;
                default:
                    throw new SystemException('请求类型错误', ExceptionType::SYSTEM_ERROR);
            }
        }catch (\Throwable $e){
            throw new SystemException('网络错误',ExceptionType::NETWORK_ERROR,$e);
        }

        $response = json_decode($requestResponse,true);
        if(empty($response)){
            throw new UnknownException('未知错误',ExceptionType::UNKNOWN_ERROR);
        }
        if ($response['code']==404) {
            throw new SystemException('接口地址不存在',ExceptionType::URL_ERROR);
        }

        if ($response['code']==402) {
            throw new AuthException('请重新登录',ExceptionType::LOGIN_EXPIRED_ERROR);
        }

        if ($response['code']==401) {
            throw new AuthException('请先登录',ExceptionType::NOT_LOGIN_ERROR);
        }

        if($response['code']!=200) {
            throw new BusinessException($response['msg'],ExceptionType::PARAMETER_ERROR);
        }
        return $response;
    }



    private static function curlPost($url, $body, $header = [], $timeout = 30): bool|string
    {
        $con = curl_init((string)$url);
        curl_setopt($con, CURLOPT_HEADER, false);
        curl_setopt($con, CURLOPT_HTTPHEADER, $header);
        curl_setopt($con, CURLOPT_POSTFIELDS, http_build_query($body));
        curl_setopt($con, CURLOPT_SSL_VERIFYPEER, false);//
        curl_setopt($con, CURLOPT_SSL_VERIFYHOST, false);//不检查ssl证书
        curl_setopt($con, CURLOPT_POST, true);
        curl_setopt($con, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($con, CURLOPT_TIMEOUT, (int)$timeout);
        curl_setopt($con, CURLOPT_ENCODING, "gzip");
        $request_response = curl_exec($con);
        if (curl_errno($con)) {
            $error = curl_error($con);
            curl_close($con);
            throw new SystemException($error, ExceptionType::NETWORK_ERROR);
        }
        curl_close($con);
        return $request_response;
    }

    private static function curlGet($url,$body = [],$header = [],$timeout = 30)
    {
        $con = curl_init();
        $query_string = http_build_query($body);
        curl_setopt($con, CURLOPT_URL, $url . '?' . $query_string); // 将参数附加到URL
        curl_setopt($con, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($con, CURLOPT_HEADER, $header);
        curl_setopt($con, CURLOPT_SSL_VERIFYPEER, false); // 不检查ssl证书
        curl_setopt($con, CURLOPT_SSL_VERIFYHOST, false); // 不检查ssl证书
        curl_setopt($con, CURLOPT_TIMEOUT, (int)$timeout);
        curl_setopt($con, CURLOPT_ENCODING, "gzip");
        $request_response = curl_exec($con);
        if (curl_errno($con)) {
            $error = curl_error($con);
            curl_close($con);
            throw new SystemException($error, ExceptionType::NETWORK_ERROR);
        }
        curl_close($con);
        return $request_response;
    }


}